package com.lnu_devteam.zongce.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lnu_devteam.zongce.common.ErrorCode;
import com.lnu_devteam.zongce.common.PageRequest;
import com.lnu_devteam.zongce.exception.BusinessException;
import com.lnu_devteam.zongce.mapper.FixedProjectMapper;
import com.lnu_devteam.zongce.model.dto.FixedProjectSaveDTO;
import com.lnu_devteam.zongce.model.dto.FixedProjectUpdateDTO;
import com.lnu_devteam.zongce.model.entity.FixedProject;
import com.lnu_devteam.zongce.model.entity.FixedScore;
import com.lnu_devteam.zongce.model.entity.User;
import com.lnu_devteam.zongce.model.vo.FixedProjectVO;
import com.lnu_devteam.zongce.model.vo.FixedScoreVO;
import com.lnu_devteam.zongce.service.FixedProjectService;
import com.lnu_devteam.zongce.service.FixedScoreService;
import com.lnu_devteam.zongce.service.UserService;
import com.lnu_devteam.zongce.utils.FuncUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author xbaoziplus
 * @description 针对表【tb_fixed_project(固定分值项目表)】的数据库操作Service实现
 * @createDate 2023-03-23 11:48:19
 */
@Service
public class FixedProjectServiceImpl extends ServiceImpl<FixedProjectMapper, FixedProject>
        implements FixedProjectService {

    @Resource
    private FixedScoreService fixedScoreService;

    @Resource
    private UserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveFixedProject(FixedProjectSaveDTO fixedProjectSaveDTO) {
        if (fixedProjectSaveDTO == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

        // 解析固定项目数据
        String fpName = fixedProjectSaveDTO.getFpName();
        if (StringUtils.isBlank(fpName)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        FixedProject fixedProject = new FixedProject();
        fixedProject.setFpName(fpName);
        // 保存固定项目
        boolean isSuccess = save(fixedProject);
        FuncUtils.isTrueToThr(!isSuccess).throwException(ErrorCode.OPERATION_ERROR);

        // 原型模式生成固定分数
        FixedScore fixedScore = new FixedScore();
        fixedScore.setFsProjectId(fixedProject.getFpId());
        // 解析固定项目加分数据
        List<FixedScore> FixedScoreList = fixedProjectSaveDTO.getFsList().stream().map(item -> {
            FixedScore cloneFixedScore = fixedScore.clone();
            // 第一级别不可为空
            if (StringUtils.isBlank(item.getFsFirstLevel())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            cloneFixedScore.setFsFirstLevel(item.getFsFirstLevel());
            // 第二级别可为空
            if (StringUtils.isNotBlank(item.getFsSecondLevel())) {
                cloneFixedScore.setFsSecondLevel(item.getFsSecondLevel());
            }
            cloneFixedScore.setFsScore(item.getFsScore());
            return cloneFixedScore;
        }).collect(Collectors.toList());

        // 批量保存固定项目分数
        isSuccess = fixedScoreService.saveBatch(FixedScoreList);
        FuncUtils.isTrueToThr(!isSuccess).throwException(ErrorCode.OPERATION_ERROR);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateFixedProject(FixedProjectUpdateDTO fixedProjectUpdateDTO) {
        if (fixedProjectUpdateDTO == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 更新固定项目
        FixedProject fixedProject = new FixedProject();
        fixedProject.setFpName(fixedProjectUpdateDTO.getFpName());
        fixedProject.setFpId(fixedProjectUpdateDTO.getFpId());
        FuncUtils.isTrueToThr(!updateById(fixedProject)).throwException(ErrorCode.OPERATION_ERROR);
        // 查询对应的加分项id
        List<Long> fsIdList = fixedScoreService.list(
                new LambdaQueryWrapper<FixedScore>()
                        .select(FixedScore::getFsId)
                        .eq(FixedScore::getFsProjectId, fixedProjectUpdateDTO.getFpId())
        ).stream().map(FixedScore::getFsId).collect(Collectors.toList());

        // 原型模式生成固定分数
        FixedScore fixedScore = new FixedScore();
        fixedScore.setFsProjectId(fixedProject.getFpId());
        List<FixedScore> needToUpdateList = fixedProjectUpdateDTO.getFsList().stream().map(item -> {
            // 过滤掉不匹配的数据
            if (item.getFsProjectId() == null || !item.getFsProjectId().equals(fixedProjectUpdateDTO.getFpId())) {
                return null;
            }
            FixedScore clone = fixedScore.clone();
            BeanUtils.copyProperties(item, clone);
            // 过滤已存在的id
            fsIdList.remove(clone.getFsId());
            return clone;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        // 批量更新
        fixedScoreService.updateBatchById(needToUpdateList);
        // 删除已去除的记录
        fixedScoreService.removeBatchByIds(fsIdList);
        return true;
    }

    @Override
    public Page<FixedProjectVO> pageVO(PageRequest pageRequest) {
        if (pageRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        int currentPage = pageRequest.getCurrentPage();
        int pageSize = pageRequest.getPageSize();
        Page<FixedProject> fpPage = page(
                new Page<>(currentPage, pageSize),
                new LambdaQueryWrapper<FixedProject>()
                        .select(FixedProject::getFpId, FixedProject::getFpName)
                        .like(StringUtils.isNotBlank(pageRequest.getKey()), FixedProject::getFpName, pageRequest.getKey())
        );
        Page<FixedProjectVO> resPage = new Page<>();
        BeanUtils.copyProperties(fpPage, resPage, "records");
        // 构建固定加分项目视图
        resPage.setRecords(
                fpPage.getRecords().stream().map(this::createFixedProjectVO).collect(Collectors.toList())
        );
        return resPage;
    }

    @Override
    public List<FixedProjectVO> listAll() {
        return  list(
                new LambdaQueryWrapper<FixedProject>().select(FixedProject::getFpId, FixedProject::getFpName)
        ).stream().map(this::createFixedProjectVO).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteFixedProject(Long fpId) {
        boolean isSuccess = removeById(fpId);
        FuncUtils.isTrueToThr(!isSuccess).throwException(ErrorCode.OPERATION_ERROR);
        isSuccess = fixedScoreService.remove(new LambdaQueryWrapper<FixedScore>().eq(FixedScore::getFsProjectId, fpId));
        FuncUtils.isTrueToThr(!isSuccess).throwException(ErrorCode.OPERATION_ERROR);
        return isSuccess;
    }

    /**
     * @description 构建固定加分项视图
     * @author xbaozi
     * @date 2023/3/29 22:57
     * @param fixedProject
     * @return FixedProjectVO
     **/
    @NotNull
    private FixedProjectVO createFixedProjectVO(FixedProject fixedProject) {
        FixedProjectVO fixedProjectVO = new FixedProjectVO();
        BeanUtils.copyProperties(fixedProject, fixedProjectVO);
        // 构建固定加分项目对应加分视图
        fixedProjectVO.setFsList(
                createFixedScoreList(fixedProject.getFpId())
        );
        return fixedProjectVO;
    }

    /**
     * @description 通过固定加分项目构建固定加分项目具体加分项集合
     * @author xbaozi
     * @date 2023/3/29 22:51
     * @param fpId  固定加分项目ID
     * @return List<FixedScoreVO>
     **/
    @NotNull
    private List<FixedScoreVO> createFixedScoreList(Long fpId) {
        return fixedScoreService.list(
                new LambdaQueryWrapper<FixedScore>().eq(FixedScore::getFsProjectId, fpId)
        ).stream().map(item -> {
            FixedScoreVO fixedScoreVO = new FixedScoreVO();
            BeanUtils.copyProperties(item, fixedScoreVO);
            return fixedScoreVO;
        }).collect(Collectors.toList());
    }
}




